﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ExtendedConsoleTraceListener.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   Defines the ExtendedConsoleTraceListener type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Collaboris.Utils.TraceListeners
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;

    public class ExtendedConsoleTraceListener : ConsoleTraceListener
    {
        private readonly Dictionary<TraceEventType, ConsoleColor> eventColour = 
            new Dictionary<TraceEventType, ConsoleColor>();


        /// <summary>
        /// Initializes a new instance of the <see cref="ExtendedConsoleTraceListener"/> class.
        /// </summary>
        public ExtendedConsoleTraceListener()
        {
            this.eventColour.Add(TraceEventType.Verbose, ConsoleColor.DarkGray);
            this.eventColour.Add(TraceEventType.Information, ConsoleColor.Gray);
            this.eventColour.Add(TraceEventType.Warning, ConsoleColor.Yellow);
            this.eventColour.Add(TraceEventType.Error, ConsoleColor.DarkRed);
            this.eventColour.Add(TraceEventType.Critical, ConsoleColor.Red);
            this.eventColour.Add(TraceEventType.Start, ConsoleColor.DarkCyan);
            this.eventColour.Add(TraceEventType.Stop, ConsoleColor.DarkCyan);
        }

        /// <summary>
        /// Writes trace information, a message, and event information to the listener specific output.
        /// </summary>
        /// <param name="eventCache">A <see cref="T:System.Diagnostics.TraceEventCache"/> object that contains the current process ID, thread ID, and stack trace information.</param>
        /// <param name="source">A name used to identify the output, typically the name of the application that generated the trace event.</param>
        /// <param name="eventType">One of the <see cref="T:System.Diagnostics.TraceEventType"/> values specifying the type of event that has caused the trace.</param>
        /// <param name="id">A numeric identifier for the event.</param>
        /// <param name="message">A message to write.</param>
        /// <PermissionSet>
        /// 	<IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
        /// 	<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode"/>
        /// </PermissionSet>
        public override void TraceEvent(
            TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
        {
            ConsoleColor originalColor = Console.ForegroundColor;
            Console.ForegroundColor = this.GetColourFromString(ref message);
            this.TraceEvent(eventCache, source, eventType, id, "{0}", message);
            Console.ForegroundColor = originalColor;
        }

        public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id)
        {
            ConsoleColor originalColor = Console.ForegroundColor;
            Console.ForegroundColor = this.GetColourFromString(ref source);
            base.TraceEvent(eventCache, source, eventType, id);
            Console.ForegroundColor = originalColor;
            
        }

        /// <summary>
        /// Writes trace information, a formatted array of objects and event information to the listener specific output.
        /// </summary>
        /// <param name="eventCache">A <see cref="T:System.Diagnostics.TraceEventCache"/> object that contains the current process ID, thread ID, and stack trace information.</param>
        /// <param name="source">A name used to identify the output, typically the name of the application that generated the trace event.</param>
        /// <param name="eventType">One of the <see cref="T:System.Diagnostics.TraceEventType"/> values specifying the type of event that has caused the trace.</param>
        /// <param name="id">A numeric identifier for the event.</param>
        /// <param name="format">A format string that contains zero or more format items, which correspond to objects in the <paramref name="args"/> array.</param>
        /// <param name="args">An object array containing zero or more objects to format.</param>
        /// <PermissionSet>
        /// 	<IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
        /// 	<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode"/>
        /// </PermissionSet>
        public override void TraceEvent(
            TraceEventCache eventCache,
            string source,
            TraceEventType eventType,
            int id,
            string format,
            params object[] args)
        {
            ConsoleColor originalColor = Console.ForegroundColor;
            Console.ForegroundColor = this.GetColourFromString(ref source);
            base.TraceEvent(eventCache, source, eventType, id, format, args);
            Console.ForegroundColor = originalColor;
        }


        /// <summary>
        /// Gets the color of the event.
        /// </summary>
        /// <param name="eventType">Type of the event.</param>
        /// <param name="defaultColor">The default color.</param>
        /// <returns></returns>
        private ConsoleColor GetColour(TraceEventType eventType, ConsoleColor defaultColor)
        {

            if (!this.eventColour.ContainsKey(eventType))
            {
                return defaultColor;
            }

            return this.eventColour[eventType];

        }

        /// <summary>
        /// Gets the color of the event.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <returns></returns>
        private ConsoleColor GetColourFromString(ref string source)
        {
            TraceEventType eventType = TraceEventType.Information;
            if (!source.ToUpper().Contains("[VERBOSE]"))
            {
                source = source.Replace("[VERBOSE] - ", string.Empty);
                eventType = TraceEventType.Verbose;
            }

            if (!source.ToUpper().Contains("[EXCEPTION]"))
            {
                source = source.Replace("[EXCEPTION] - ", string.Empty);
                eventType = TraceEventType.Error;
            }

            if (!source.ToUpper().Contains("[INFO]"))
            {
                source = source.Replace("[INFO] - ", string.Empty);
                eventType = TraceEventType.Information;
            }

            if (!source.ToUpper().Contains("[WARNING]"))
            {
                source = source.Replace("[WARNING] - ", string.Empty);
                eventType = TraceEventType.Warning;
            }
            
            return this.eventColour[eventType];
        }
    }
}